/*********************************************
 *WiFi configration for ESP8266.
 *Author: openthings@163.com. 
 *copyright&GPL V2.
 *Last modified 2014-10-20.
 **********************************************/

#include "c_types.h"
#include "user_interface.h"
#include "xc_version.h"
#include "version.h"
#include "espconn.h"
#include "mem.h"
#include "xc.h"
#include "osapi.h"
#include "driver/uart.h"
#include "xc_cmd.h"
#include "xc_cmd_wifi.h"

uint8_t xc_wifiMode;
at_mdStateType mdState = m_unlink;
os_timer_t at_japDelayChack;
extern BOOL specialAtState;
extern at_stateType at_state;

extern cmd_functionType cmd_fun[xc_cmdNum];

/*********************************************
 *查询或设置WiFi工作模式。
 * 1-STA，网卡模式。
 * 2-AP，路由器模式。
 * 3-AP+STA，网卡+路由器模式。
 *********************************************/
void xc_cmd_CWMODEQ(uint8_t id, char* pParam)
{
	char temp[32];
	xc_wifiMode = wifi_get_opmode();
	os_sprintf(temp, "\r\n%s:%d\r\n", cmd_fun[id].cmdName, xc_wifiMode);
	sendInfoAll(temp);
}

void xc_cmd_CWMODE(uint8_t id, char* pParam)
{
	uint8_t mode;
	mode = atoi(pParam);
	
	char temp[32];
	os_sprintf(temp, "\r\nMODE:%d\r\n", mode);
	sendInfoAll(temp);
	
	if ((mode == 1) ||(mode == 2) || (mode == 3))	{
		ETS_UART_INTR_DISABLE();
		wifi_set_opmode(mode);
		ETS_UART_INTR_ENABLE();
		xc_wifiMode = mode;
		sendInfoAll("\r\nOK\r\n");
	}
	else	{
		sendInfoAll("\r\nerror\r\n");
	}
}

/*********************************************
 *查询接入点(AP)的频道信息。
 *********************************************/
void xc_cmd_CWCHANNELQ(uint8_t id, char* pParam)
{
	uint8_t iChannel = wifi_get_channel();
	char temp[32];
	os_sprintf(temp, "\r\nCHANNEL:%d\r\n", iChannel);
	sendInfoAll(temp);
}

void xc_cmd_CWCHANNEL(uint8_t id, char* pParam)
{
	uint8_t iChannel = atoi(pParam);
	char temp[32];
	if (wifi_set_channel(iChannel)) {
		os_sprintf(temp, "\r\nCHANNEL:%d\r\n", iChannel);
		sendInfoAll(temp);	
	}else{
		os_sprintf(temp, "\r\nSET CHANNEL FAIL:%d\r\n", iChannel);
		sendInfoAll(temp);
	}
}

/*********************************************
 *查询接入点(AP)的SSID信息。
 *********************************************/
void xc_cmd_CWJAPQ(uint8_t id, char* pParam)
{
	char temp[64];
	struct station_config stationConf;
	if (wifi_station_get_config(&stationConf)==TRUE) {
		os_sprintf(temp, "\r\n%s:%s,%s\r\n", cmd_fun[id].cmdName, stationConf.ssid,stationConf.password);
		sendInfoAll(temp);
	}	else	{
		sendInfoAll("\r\nERROR\r\n");
	}
}

/*********************************************
 * 配置接入点的SSID和PWD信息。
 *********************************************/
void xc_cmd_CWJAP(uint8_t id, char* pParam)
{
	//如果ap_ssid为空，则为重新连接。
	if (pParam==NULL) {
			wifi_station_disconnect();
			xc_cmd_CWCAP(id, pParam);
			return;
	}

	char delims[] = ",";
	char *ap_ssid = strtok( pParam, delims );
	char *ap_pwd =  strtok( NULL, delims );

	char temp[64];
	os_sprintf(temp, "\r\nJAP:SSID-%s,PWD-%s\r\n", ap_ssid, ap_pwd);
	sendInfoAll(temp);

	//无效的SSID.
	if (os_strlen(ap_ssid)<1) {
		sendInfoAll("\r\ninvalid ssid.\r\n");
		return;
	}
	xc_connectAP(ap_ssid,ap_pwd);
}

void xc_connectAP(char* ap_ssid,char* ap_pwd)
{
	//复制设置参数到系统。
	struct station_config stationConf;
	strcpy( (char*) &stationConf.ssid, ap_ssid);
	strcpy( (char*) &stationConf.password, ap_pwd);
	stationConf.bssid_set = 0;
	
	//重新连接WiFi热点-有可能不成功，需检查IP。
	wifi_station_disconnect();
	ETS_UART_INTR_DISABLE();
	wifi_station_set_config(&stationConf);
	ETS_UART_INTR_ENABLE();
	//wifi_station_set_auto_connect();
	wifi_station_connect();
	//xc_cmd_CWCAP(id, pParam);	
}
/*********************************************
 *连接无线接入点。
 *********************************************/
void xc_cmd_CWCAP(uint8_t id, char* pParam)
{
	if (wifi_station_connect()==TRUE){
		sendInfoAll("connect ap successs.\r\n");
	}
	else{
		sendInfoAll("connect ap fail.\r\n");
	}
}

/*********************************************
 *退出无线接入点的连接。
 *********************************************/
void xc_cmd_CWQAP(uint8_t id, char* pParam)
{
	wifi_station_disconnect();
	sendInfoAll("quit ap.\r\n");
}

/*********************************************
 *扫描接入点信息。
 *********************************************/
void xc_cmd_CWLAP(uint8_t id, char* pParam)
{		
	if (wifi_station_scan(NULL, scan_done)) {
		specialAtState = FALSE;
	}	else	{
		sendInfoAll("CWLAP error.\r\n");
	}
}

/**********************************************
  * @brief  Wifi ap scan over callback to display.
  * @param  arg: contain the aps information
  * @param  status: scan over status
  * @retval None
  *********************************************/
static void ICACHE_FLASH_ATTR scan_done(void *arg, STATUS status)
{
	uint8 ssid[33];
	char temp[128];

	if (status == OK)
	{
		struct bss_info *bss_link = (struct bss_info *)arg;
		bss_link = bss_link->next.stqe_next;//ignore first

		while (bss_link != NULL) {
			os_memset(ssid, 0, 33);
			if (os_strlen(bss_link->ssid) <= 32) {
				os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
			} else {
				os_memcpy(ssid, bss_link->ssid, 32);
			}
			os_sprintf(temp,"+CWLAP:%d,%s,%d,"MACSTR",%d\r\n",
						bss_link->authmode, ssid, bss_link->rssi,
						MAC2STR(bss_link->bssid),bss_link->channel);
			sendInfoAll(temp);
			bss_link = bss_link->next.stqe_next;
		}
		sendInfoAll("OK\r\n");
	}	else	{
			os_sprintf(temp,"error, scan status %d\r\n", status);
			sendInfoAll(temp);
	}
	//specialAtState = TRUE;
	at_state = at_statIdle;
}

/*********************************************
 *模块的SoftAP的参数查询。
 *********************************************/
void xc_cmd_CWSAPQ(uint8_t id, char* pParam)
{
	struct softap_config apConfig;
	char temp[128];
	
	wifi_softap_get_config(&apConfig);
	os_sprintf(temp,"%s:\"%s\",\"%s\",%d,%d\r\n", cmd_fun[id].cmdName,
			apConfig.ssid,apConfig.password,
			apConfig.channel,
			apConfig.authmode);
	sendInfoAll(temp);
	//sendInfoAll("OK\r");;
}

/*********************************************
 *模块的SoftAP的参数设置。
 * @+CWSAP=SSID,PWD,CHANNEL,AUTHMODE。
 *********************************************/
void xc_cmd_CWSAP(uint8_t id, char* pParam)
{
	char delims[] = ",";
	char *sap_ssid = strtok( pParam, delims );
	char *sap_pwd =  strtok( NULL, delims );
	char *sap_channel =  strtok( NULL, delims );
	char *sap_authmode =  strtok( NULL, delims );

	char temp[128];
	int8_t nchannel,nauthmode;
	struct softap_config apConfig;
	
	//For Debug.
	os_sprintf(temp,"SAP=:%s,%s,%s,%s\r\n",	sap_ssid,sap_pwd,
	            sap_channel,sap_authmode);
	sendInfoAll(temp);

	//无效的SSID for softAP，直接返回。
	if (os_strlen(sap_ssid)<1) {
		sendInfoAll("invalid ssid.\r\n");
		return;
	}
	
	wifi_softap_get_config(&apConfig);
	strcpy(apConfig.ssid, sap_ssid);
	strcpy(apConfig.password, sap_pwd);

	//Channel设置，不合规的保持不变。
	nchannel = atoi(sap_channel);
	if ((nchannel>=1)&&(nchannel<=13)) {
		apConfig.channel = nchannel;
	} else {
		sendInfoAll("error,invalid channel.\r\n");
	}
	
	//加密与授权模式。
	nauthmode = atoi(sap_authmode);
	if ((nauthmode >= 0)&&(nauthmode < 5)) {
		apConfig.authmode = nauthmode;
	}else {
		sendInfoAll("error,invalid authmode.\r\n");
	}
	
	if ((apConfig.authmode != 0)&&(strlen(sap_pwd) < 5)) {
		sendInfoAll("error,pwd must >=5 when authmode!=0.\r\n");
		return;
	}
		
	ETS_UART_INTR_DISABLE();
	wifi_softap_set_config(&apConfig);
	ETS_UART_INTR_ENABLE();
}

/*********************************************
 *查看已接入设备的IP，返回列表。
 *********************************************/
void xc_cmd_CWLIF(uint8_t id, char* pParam)
{
	struct station_info *station;
	struct station_info *next_station;
	char temp[128];

	if (xc_wifiMode == STATION_MODE) {
		sendInfoAll("Mode STATION not support CWLIF.\r\n");
		return;
	}
	
	station = wifi_softap_get_station_info();
	while (station)	{
		os_sprintf(temp, "%d.%d.%d.%d,"MACSTR"\r\n",
				IP2STR(&station->ip), MAC2STR(station->bssid));
		sendInfoAll(temp);
		next_station = STAILQ_NEXT(station, next);
		os_free(station);
		station = next_station;
	}
	sendInfoAll("OK\r\n");
}

/***End of XCMD for WiFi Module*****************/
